package com.jay.media.music.core.db

import android.annotation.SuppressLint
import android.content.Context
import android.media.MediaMetadata
import androidx.room.Room
import com.jay.media.music.core.player.MusicPlayManager
import com.jay.media.music.core.provider.METADATA_TRACK_SOURCE
import com.jay.media.music.core.util.MusicExt.toMusic
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.concurrent.ConcurrentHashMap

/**
 * @author xuzhou4
 * @date 2022/2/14
 */
class MusicManager {

    companion object {
        private val INSTANCE by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            MusicManager()
        }

        fun get(): MusicManager {
            return INSTANCE
        }
    }

    private lateinit var mContext: Context
    private lateinit var mMusicDao: MusicDao
    private var mFavorMusicMap: MutableMap<String, Music> = ConcurrentHashMap()
    private var mCoroutineScope = CoroutineScope(Dispatchers.IO)

    fun init(context: Context) {
        this.mContext = context.applicationContext
        this.mMusicDao = Room.databaseBuilder(mContext, MusicDataBase::class.java, "music")
            .allowMainThreadQueries()
            .build()
            .musicDao()

        mCoroutineScope.launch {
            mFavorMusicMap = queryFavorList().associateBy { m -> m.data }.toMutableMap()
        }
    }

    @SuppressLint("WrongConstant")
    fun insertPlayHistory(mediaMetadata: MediaMetadata) {
        insertPlayHistory(mediaMetadata.toMusic())
    }

    private fun insertPlayHistory(music: Music) {
        mCoroutineScope.launch {
            var insert = false
            var qMusic = mMusicDao.queryByData(music.data)

            if (qMusic == null) {
                insert = true
                qMusic = music
            }

            qMusic.playHistoryType = 1
            qMusic.playHistoryOrder = 0
            qMusic.playHistoryTime = System.currentTimeMillis()

            if (insert) {
                mMusicDao.insert(qMusic)
            } else {
                mMusicDao.update(qMusic)
            }
        }
    }

    fun queryPlayHistory(): List<Music> {
        return mMusicDao.queryPlayHisList()
    }

    fun insertPlayList(mediaMetadata: MediaMetadata) {
        updatePlayList(mediaMetadata.toMusic(), true)
    }

    fun removePlayList(mediaMetadata: MediaMetadata) {
        updatePlayList(mediaMetadata.toMusic(), false)
    }

    fun updatePlayList(music: Music, playList: Boolean) {
        mCoroutineScope.launch {
            var insert = false
            var qMusic = mMusicDao.queryByData(music.data)

            if (qMusic == null) {
                insert = true
                qMusic = music
            }

            qMusic.playListType = if (playList) 1 else 0
            qMusic.playListOrder = 0
            qMusic.playListTime = if (playList) System.currentTimeMillis() else 0L

            if (insert) {
                mMusicDao.insert(qMusic)
            } else {
                mMusicDao.update(qMusic)
            }
        }
    }

    fun queryPlayList(): List<Music> {
        return mMusicDao.queryPlayList()
    }

    @SuppressLint("WrongConstant")
    fun operateFavor(mediaMetadata: MediaMetadata, favor: Boolean) {
        insertFavor(mediaMetadata.toMusic(), favor)
    }

    private fun insertFavor(music: Music, favor: Boolean) {
        mCoroutineScope.launch {
            var insert = false
            var qMusic = mMusicDao.queryByData(music.data)

            if (qMusic == null) {
                insert = true
                qMusic = music
            }

            qMusic.favorType = if (favor) 1 else 0
            qMusic.favorTypeOrder = 0
            qMusic.favorTypeTime = System.currentTimeMillis()

            if (insert) {
                mMusicDao.insert(qMusic)
            } else {
                mMusicDao.update(qMusic)
            }

            if (qMusic.favorType == 1) {
                mFavorMusicMap[qMusic.data] = qMusic
            } else {
                mFavorMusicMap.remove(qMusic.data)
            }

            MusicPlayManager.get()
                .notifyMediaMetadataChange(MusicPlayManager.get().getCurrMediaMetadata())
        }
    }

    fun queryFavorList(): MutableList<Music> {
        return mMusicDao.queryFavorList()
    }

    fun isFavor(mediaMetadata: MediaMetadata): Boolean {
        return mFavorMusicMap[mediaMetadata.getString(METADATA_TRACK_SOURCE) ?: ""] != null
    }
}